﻿#include "record_set.h"
#include "cross_com.h"
#include "storage_api.h"
#include  "storage_callback.h"

#ifdef  _SIMULATE_RECORD_
#include "MultiCHData.h"
#endif

uint32_t CRecordSet::m_procBIT = 0;
extern StorageConfig	g_storageCfg;
extern CFile_manager_arr g_pFileMangerArr;

int CRecordSet::MANUAL_SWITCH  = -1;

extern STORAGE_STATUS_CBAK        g_status_bak;

CRecordSet::CRecordSet(CFile_manager_arr *pDiskCfg,int chnnNum)
{
	m_recStatusBIT		= 0;
	m_bThreadLive	= false;
	m_bTimeTheadLive= false;
	m_chnnNum	   = chnnNum;
	m_pIndexSet    = pDiskCfg;
	m_bPause	   = true;
	m_bPrepare	   = true;
	m_diskFullCnt  = 0;
	m_nPrepareSecs = 5;
	m_pRecordCamera = new RECORD_CAMERA[chnnNum];
	memset(m_pRecordCamera,0,sizeof(RECORD_CAMERA)*chnnNum);

	int iCH;

	for (iCH = 0; iCH < chnnNum; iCH++)
	{
		m_pRecordCamera[iCH].pRecDataProc = new CRecord1CHProc(iCH,DATA_SOURCE_RECORD);
		m_pRecordCamera[iCH].bActive      = true;
		m_pRecordCamera[iCH].bWithAudio   = true;

	}

	RECORD_CTL_PARAM tmpParam;
	memset(&tmpParam,0,sizeof(RECORD_CTL_PARAM));
	m_vecRecParam.reserve(chnnNum);
	for(int i = 0; i < chnnNum; i++)
	{
		m_vecRecParam.push_back(tmpParam);
	}

//	for(int i = 0; i < chnnNum; i++)
//	{
//	//	m_vecRecParam[i].pSchedule = new CSchedule();
//	}

	m_bNeedStop  = true;

	m_procBIT |= PROC_DISK_1STREPORT;
	m_wt_data = 0;
	m_wt_bak  = 0;
	m_wt_speed= 0;
	time(&m_lastCoutTime);
	time(&m_lastCeckDiskFullTm);
	m_bDiskScanning = false;
	memset(&m_curFrm,0,sizeof(FIFO_BUF_INFO));
	m_lastFrmSz = 0;
	m_show_cnt = 0;
	m_bEvtStop = true;
}

CRecordSet::~CRecordSet()
{
	int iCH;

	for (iCH = 0; iCH < m_chnnNum; iCH++)
	{
		if(NULL != m_pRecordCamera[iCH].pRecDataProc)
		{
			delete m_pRecordCamera[iCH].pRecDataProc;
		}
	}

	delete [] m_pRecordCamera;

}

int CRecordSet::InitParm()
{
	int iCH;
	int buf_size = 0;
	for (iCH = 0; iCH < m_chnnNum; iCH++)
	{
		//确定当前通道是否开启录像
		if(g_storageCfg.chInfo[iCH].enable)
		{
			buf_size = g_storageCfg.chInfo[iCH].rec_cache_sz;
			m_pRecordCamera[iCH].pRecDataProc->GetRecWriter()->Init(true,buf_size);
		}
	}

	return 0;
}
int CRecordSet::Start()
{
	m_bNeedStop = false;

	m_dataThdID = Cross_CreateThread((cross_start_routine) DataProcThread, (void *)this,NULL, SIZE_128KB);

	m_timeThdID = Cross_CreateThread((cross_start_routine) TimerThread, (void *)this, NULL,SIZE_128KB);

	return 0;
}

void CRecordSet::StopProc()
{
	//停止录像，并产生录像段
	for(int ch = 0; ch < m_chnnNum ;ch++)
	{
		StopRecord(ch, RECORD_STOP,true,true);
		m_recStatusBIT &= ~(1 <<ch);
	}

	m_recStatusBIT = 0;
	CrossSleep(10);

	TRACE("Start wait for stop record.\n");

	for(size_t i = 0 ; i < m_vecRecParam.size(); i++)
	{
		m_vecRecParam[i].recTypeBak = m_vecRecParam[i].recType    = RECORD_NONE;
		m_vecRecParam[i].inStatus   = STREAM_DATALOST;
	}

	for (int ch = 0 ; ch < m_chnnNum; ch++)
	{
		m_pRecordCamera[ch].bEnable = false;
	}
	//回调最后的录像和磁盘状态
	CallbackRecStatus(false);
}

void CRecordSet::Stop()
{
	if( 0 == m_recStatusBIT)
	{
		return ;
	}
	m_bNeedStop = true;

// 	{
// 		//停止录像，并产生录像段
// 		for(int ch = 0; ch < m_chnnNum ;ch++)
// 		{
// 			StopRecord(ch, RECORD_STOP,true,true);
// 			m_recStatusBIT &= ~(1 <<ch);
// 		}
// 		m_recStatusBIT = 0;
// 		CrossSleep(10);
// 		int nWaitCnt = 300;
// 		TRACE("Start wait for stop record.\n");
// 		while(!m_bPause)
// 		{
// 			TRACE(".");
// 			CrossSleep(10);
// 			if( 0 > nWaitCnt--)
// 			{
// 				break;
// 			}
// 		}
// 		for(size_t i = 0 ; i < m_vecRecParam.size(); i++)
// 		{
// 		    m_vecRecParam[i].recTypeBak = m_vecRecParam[i].recType    = RECORD_NONE;
// 			m_vecRecParam[i].inStatus   = STREAM_DATALOST;
// 		}
//
// 		for (int ch = 0 ; ch < m_chnnNum; ch++)
// 		{
// 			m_pRecordCamera[ch].bEnable = false;
// 		}
// 		//回调最后的录像和磁盘状态
// 	//	CallbackRecStatus(false);
// 		CallbackDiskStatus();
// 	}
	TRACE("\nEnd wait for stop record. Active \n");
}

void CRecordSet::CloseRec()
{
	//停止录像，并产生录像段
	for(int ch = 0; ch < m_chnnNum ;ch++)
	{
		RECORD_CAMERA*  pCamera = &m_pRecordCamera[ch];
		if(!pCamera->bActive)
		{
			TRACE_ERR("No Active record channel");
			return;
		}

		CRecord1CHProc* pRecDataProc = pCamera->pRecDataProc;
		pRecDataProc->Close();
	}
}
void CRecordSet::StopRecordOfDisk(char * device)
{
	CRecord1CHProc* pRecDataProc = NULL;
	int ret = 0;
	for(int ch = 0 ; ch < m_chnnNum; ch++)
	{
		pRecDataProc = m_pRecordCamera[ch].pRecDataProc;
		ret = pRecDataProc->InterruptRecord(device);
	}
	TRACE_ERR("Dev %s interrupt record ret %d .\n",device,ret);
}
void CRecordSet::PauseRecord(int ch)
{
	m_pRecordCamera[ch].pRecDataProc->Pause();
}

void CRecordSet::StartRecord(int ch, int type, char *pText, uint32_t textLen)
{
	//通道参数不合法
	if(ch >= m_chnnNum)
	{
		TRACE_ERR("Over max channel num CH%02d.\n",ch);
		return ;
	}

// 	if( m_bDiskScanning && 0 == g_pFileMangerArr.GetRecordDiskNum())
// 	{
// 		TRACE_ERR("CH%02d NO record disk for record .\n",ch);
// 		return ;
// 	}

	RECORD_CAMERA*  pCamera		= &m_pRecordCamera[ch];
	CRecord1CHProc* pRecDataProc= pCamera->pRecDataProc;
	if(!pCamera->bActive)
	{
		TRACE_ERR("No Active record channel");
		return ;
	}
	bool bClose = false;
	CCross_LockAuto tempLock(&m_lock);
	int curType = m_vecRecParam[ch].recType;

	if(type == curType)
	{
		pCamera->bActive = true;
		pCamera->bEnable = true;
		return ;
	}

	m_recStatusBIT |= 1 << ch;
	switch(type)
	{
	case RECORD_SCHEDULE:
		if(curType > type)
		{
			return;
		}
		m_vecRecParam[ch].recType = type;
		break;
	case RECORD_MANUAL:
		if(RECORD_IOALARM != curType )
		{
			if(type < curType)
			{
				return;
			}
		}
		if(type > curType && curType != RECORD_NONE )
		{
			pRecDataProc->StopRecord(curType,bClose,type);
		}
		m_vecRecParam[ch].recType = type;
		break;
	case RECORD_MOTION:
	//case RECORD_IOALARM:
	case RECORD_SHELTER:
	case RECORD_BEHAVIOR:
		if(curType & type)
		{
			return;
		}

		pRecDataProc->StopRecord(curType,bClose,type);
		if((curType >= RECORD_MOTION)&&
			(curType <= RECORD_XX))
		{
			m_vecRecParam[ch].recType = curType|type;
		}
		else
		{
			m_vecRecParam[ch].recType = type;
		}
		break;
	case RECORD_IOALARM:
		if(curType & type)
		{
			return;
		}
	//	pRecDataProc->StopRecord(curType,bClose,type);
		m_vecRecParam[ch].recType = type;
		break;
	default:
		break;
	}
	pCamera->bActive = true;
	pCamera->bEnable = true;
	m_procBIT |= PROC_RECORD_STATUS;
}

void CRecordSet::StopRecord(int ch, int type ,bool bCloseFile,bool bForce)
{
	if(ch >= m_chnnNum )
	{
		TRACE_ERR("Over max channel  CH%02d.\n",ch);
		return ;
	}

	RECORD_CAMERA*  pCamera = &m_pRecordCamera[ch];
	if(!pCamera->bActive)
	{
		TRACE_ERR("No Active record channel");
		return ;
	}

	CRecord1CHProc* pRecDataProc = pCamera->pRecDataProc;
	CCross_LockAuto tempLock(&m_lock);
	int localType =  m_vecRecParam[ch].recType ;

	switch(type)
	{
	case RECORD_STOP:
		break;
	case RECORD_NONE:
		break;
	case RECORD_SCHEDULE:
		if(type < localType)
		{
			return;//goto END_OUT;
		}
		break;
	case RECORD_MANUAL:
        if(type == localType)
        {
            pCamera->bEnable = false;
            m_recStatusBIT &= ~(1 << ch);
        }

		if(!bForce)
		{
			if(!(localType & type))
			{
				return;//goto END_OUT;
			}
		}
		break;
	case RECORD_MOTION:
	case RECORD_IOALARM:
	case RECORD_SHELTER:
	case RECORD_BEHAVIOR:
		if(!bForce)
		{
			if(!(localType & type))
			{
				//goto END_OUT;
				return;
			}

		}
		break;
	default:
		break;
	}

//	pCamera->bEnable = false;
	TRACE("Stop record type %d locaType %d.\n",type,localType);
	int ret = 0;
    ret = pRecDataProc->StopRecord(localType,bCloseFile,type);

	switch(type)
	{
	case RECORD_STOP:
	case RECORD_NONE:
		m_vecRecParam[ch].recType = RECORD_NONE;
		break;
	case RECORD_SCHEDULE:
		m_vecRecParam[ch].recType = RECORD_NONE;
		break;
	case RECORD_MANUAL:
		m_vecRecParam[ch].recType = RECORD_NONE;
		break;
	case RECORD_MOTION:
	case RECORD_IOALARM:
	case RECORD_SHELTER:
	case RECORD_BEHAVIOR:
		m_vecRecParam[ch].recType = localType &= ~type;
		break;
	default:
		break;
	}
}

char * CRecordSet:: GetRecFile(int ch)
{
	if(ch >= m_chnnNum )
	{
		TRACE_ERR("Over max channel  CH%02d.\n",ch);
		return NULL;
	}


	RECORD_CAMERA*  pCamera = &m_pRecordCamera[ch];

	return pCamera->pRecDataProc->GetRecFile();
}
void CRecordSet::SetAlarmTime(int ch,int type,int recTimeSes)
{
	if(ch >= m_chnnNum )
	{
		TRACE_ERR("Over max channel  CH%02d.\n",ch);
		return ;
	}

#ifdef _WIN32
    recTimeSes = recTimeSes;
#else
    if(recTimeSes < 10)
    {
        recTimeSes = 30;
    }
#endif
	RECORD_CTL_PARAM* pCtrl = &m_vecRecParam[ch] ;

	switch(type)
	{
	case RECORD_MOTION:
		pCtrl->montionTm      = recTimeSes;
		time(&pCtrl->startMontim);
		break;
	case RECORD_IOALARM:
		//由于DevMng模块触发录像的间隔和录像的持续时间一致，
		//所以会导致一个现象，就是开着手动录像的时候，IO一直触发时，中间可能出现一个手动录像图标闪一下的现象
		pCtrl->ioAlarmTm      = recTimeSes + 1;
		time(&pCtrl->startIOAlarm);
		break;
	case RECORD_SHELTER:
		pCtrl->shelterTm	  = recTimeSes;
		time(&pCtrl->startShleter);;
		break;
	case RECORD_BEHAVIOR:
		pCtrl->behaviorTm	  = recTimeSes;
		time(&pCtrl->startBehavior);;
		break;
	default:
		TRACE_ERR("Unsupport recordType. %d\n",type);
		return;
		break;
	}
}

void CRecordSet::DealAlarmRec()
{
	int ch = 0;
	time_t now;
	RECORD_CTL_PARAM* pCtrl = NULL;
	int recType = RECORD_NONE;
	int endType = RECORD_NONE;
	int bitType = 0;
	int type = 0;
	int64_t lastTm = 0;

	time(&now);
//	CCross_LockAuto tempLock(&m_lock);

	for(ch = 0;ch < m_chnnNum; ch++)
	{
		pCtrl = &m_vecRecParam[ch] ;
		RECORD_CAMERA*  pCamera = &m_pRecordCamera[ch];
		lastTm = pCamera->pRecDataProc->GetLastFrmTime(); //获取最后一帧的时间,获取到录像文件中最后一帧的录像数据
		if(lastTm != 0)
		{
			now = lastTm/STFS_1SEC_MS;
		}

		recType = pCtrl->recType;;
		switch(recType)
		{
		case RECORD_NONE:
		case RECORD_SCHEDULE:
		case RECORD_MANUAL:
			continue;

		case RECORD_MOTION:
			if(ABS(now - pCtrl->startMontim) > pCtrl->montionTm)
			{
#ifdef _CBS_DBG_
				TRACE_CBS("Montion time %d.\n",pCtrl->montionTm);
				PrintTimeSec(pCtrl->startMontim,now,"Montion time");
#endif
				StopRecord(ch,recType);
				goto NEXT_CH;
			}
			break;
		case RECORD_IOALARM:
			if(ABS(now - pCtrl->startIOAlarm) > pCtrl->ioAlarmTm)
			{
				if(m_bEvtStop)
				{
					StopRecord(ch,recType,true,true);
				}
				else
				{
					StopRecord(ch,recType);
				}
				goto NEXT_CH;
			}
			break;
		case RECORD_SHELTER:
			if(ABS(now - pCtrl->startShleter) > pCtrl->shelterTm)
			{
				StopRecord(ch,recType);
				goto NEXT_CH;
			}
			break;
		case RECORD_BEHAVIOR:
			if(ABS(now - pCtrl->startBehavior) > pCtrl->behaviorTm)
			{
				StopRecord(ch,recType);
				goto NEXT_CH;
			}
			break;
		default:
			break;
		}

		if( recType >= RECORD_MOTION &&
			recType < RECORD_XX )
		{
			for(bitType = 2;bitType < 8 ; bitType++)
			{
				type = 1<<bitType;
				if(recType & type)
				{
					switch(type)
					{
					case RECORD_MOTION:
						if(ABS(now - pCtrl->startMontim) > pCtrl->montionTm)
						{
							endType |= type;
						}
						break;
					case RECORD_IOALARM:
						if(ABS(now - pCtrl->startIOAlarm) > pCtrl->ioAlarmTm)
						{
							endType |= type;
						}
						break;
					case RECORD_SHELTER:
						if(ABS(now - pCtrl->startShleter) > pCtrl->shelterTm)
						{
							endType |= type;
						}
						break;
					case RECORD_BEHAVIOR:
						if(ABS(now - pCtrl->startBehavior) > pCtrl->behaviorTm)
						{
							endType |= type;
						}
						break;
					}
				}
			}

			if(RECORD_MOTION <= endType)
			{
				StopRecord(ch,endType);
			}
		}
NEXT_CH:
		;
	}
}

int CRecordSet::GetRecordType(int ch)
{
	if(!m_pRecordCamera[ch].pRecDataProc->Recording())
	{
		return RECORD_NONE;
	}

	return m_vecRecParam[ch].recType;
}


void CRecordSet::SetEnable(int ch, uint16_t bEnable)
{
	m_pRecordCamera[ch].bEnable = bEnable;
}

void CRecordSet::SetEnableAudio(int ch, uint16_t bEnable)
{
	m_pRecordCamera[ch].bWithAudio = bEnable;
}

int CRecordSet::GetAudioRecEnable(int ch)
{
	return m_pRecordCamera[ch].bWithAudio;
}


void CRecordSet::ChanageType(int ch,int type)
{
	m_vecRecParam[ch].recType = type;
}

void CRecordSet::SetFileType(int ch, int fileType)
{
	m_pRecordCamera[ch].pRecDataProc->Init(fileType);
}

void CRecordSet::SetRecordAudio(int ch, bool bWithAudio)
{
	m_pRecordCamera[ch].bWithAudio = bWithAudio;
}


void CRecordSet::SetRecycleRecord(bool bRecycle)
{
	for(int i = 0 ; i < m_chnnNum; i++)
	{
		m_pRecordCamera[i].pRecDataProc->SetRecycleRecord(bRecycle);
	}

	//如何开启循环录像则需要把磁盘满的状态关闭掉。
	if(bRecycle)
	{
	//	int  ret = g_pFileMangerArr.GetRecordDiskNum();
		//重新刷新激活磁盘状态,可以去掉磁盘满的状态
	//	g_pFileMangerArr.CallBakDiskActive(0,ret);

		TRACE("Open record Cycle Mode . Need refresh disk status.\n");
	}
}

void CRecordSet::SetPrepareRec(bool bEnable,int nSecs)
{
	if(0 == nSecs)
	{
		m_bPrepare = false;
	}
	else
	{
		m_bPrepare =true;
	}
	CRecord1CHProc::PREPARE_SECS = m_nPrepareSecs = nSecs;
}

void CRecordSet::SetRedundancyRec(int ch, bool bRedundancy)
{
	for(int i = 0 ; i < m_chnnNum; i++)
	{
		m_pRecordCamera[i].bRedundancy = bRedundancy;
	}
}

//设置预录像
void CRecordSet::SetPreAlarmTime(int ch, uint16_t preAlarmTime)
{
	m_vecRecParam[ch].preHoldTime = preAlarmTime;
}

void CRecordSet::SetPostAlarmTime(int ch, int type, uint16_t postAlarmTime)
{
	m_vecRecParam[ch].preHoldTime = postAlarmTime;
}

void CRecordSet::SetSchedule(int ch,const SCHDULE_REC & schedule)
{
	m_vecRecParam[ch].pSchedule->SetFSAPISchedule(schedule);
}

void CRecordSet::GetSchedule(int ch,SCHDULE_REC* pSchedule)
{
	m_vecRecParam[ch].pSchedule->GetFSAPIScheduleTime(pSchedule);
}



void CRecordSet::SetReducDisk(uint16_t *pDiskIndex, uint32_t reducDiskNum)
{
	for(int i = 0 ; i < m_chnnNum; i++)
	{
		m_pRecordCamera[i].bRedundancy = true;
	}
}

void CRecordSet::SetResolution(int width,int height,int channel)
{
	for(int i = 0 ; i < m_chnnNum; i++)
	{
		m_pRecordCamera[i].pRecDataProc->SetResolution(width,height);
	}
}


void CRecordSet::SetStartRecordDisk(int diskIdx)
{
	for(int i = 0 ; i < m_chnnNum; i++)
	{
		m_pRecordCamera[i].pRecDataProc->SetRecDiskIdx(diskIdx);
	}
}

bool CRecordSet::IsOpenManualRecord(int ch)
{
	if(g_storageCfg.chInfo[ch].enable)
	{
		return true;
	}

	return false;
}

int CRecordSet::IsContentRecord(int ch)
{
	if(ch >= m_chnnNum)
	{
		TRACE_ERR("Over max channel num CH%02d.\n",ch);
		return ERR_PARAM;
	}
    CRecord1CHProc* pRecDataProc= m_pRecordCamera[ch].pRecDataProc;
#ifdef _WIN32
	if(pRecDataProc->IsPause())
	{
		return ERR_PARAM;
	}
#endif
	if(!pRecDataProc->Recording())
	{
		if( ! pRecDataProc->GetCycleStatus() &&
			0 == m_pIndexSet->GetLeafRecNum())
		{
		//	TRACE("Record disk is full.\n");
			return ERR_INDEX_NORECIDX;
		}
	}

	//未开启录像类型
	if(RECORD_NONE == m_vecRecParam[ch].recType)
	{
		if(MANUAL_SWITCH>>ch & 0x01)
		{
			m_vecRecParam[ch].recType = RECORD_MANUAL;
			return 0;
		}
		return ERR_PARAM;
	}

	return 0;
}
bool CRecordSet::IsNeedDiskFullAlarm()
{
	int leafNum = m_pIndexSet->GetLeafFileNum();

	if( (0 == leafNum) &&
        !g_storageCfg.bCycleRec&&
		IsHaveChannelStopRec())
	{
		TRACE_ERR("LeafNum %d .\n",leafNum);
		return true;
	}

    return false;
}

bool CRecordSet::IsHaveChannelStopRec()
{
	int ch = 0;

	for(ch = 0; ch < m_chnnNum ; ch++)
	{
		if(!m_pRecordCamera[ch].pRecDataProc->Recording())
		{   //只要有任何一个通道停止则返回
			return true;
		}
	}

	return false;
}

bool CRecordSet::IsChReocrding(int ch)
{
	if(m_pRecordCamera[ch].pRecDataProc->Recording())
	{
		return true;
	}

	return false;
}


bool  CRecordSet::IsRecording(char * dev)
{
	if(m_pRecordCamera[0].pRecDataProc->Recording())
	{   //只要有任何一个通道停止则返回
		if(strstr(m_pRecordCamera[0].pRecDataProc->GetDevName(),dev))
		{
			return true;
		}
	}

	return false;
}

int CRecordSet::WriteFrameDataProc(int ch,uchar_t * frameBuf, int bufSize )
{
	int ret = 0;
	const int LOW_WATER   = 10;
	int curWater  = 0;
	int frameSize = 0;
	CRecord1CHProc* pRecDataProc= m_pRecordCamera[ch].pRecDataProc;
	RECORD_CTL_PARAM  *pRecCtrl      = &m_vecRecParam[ch];;
	do
	{
		 ret =  GetOneFrameData(ch,frameBuf,bufSize);
		 if(ret > 0)
		 {
			 pRecCtrl->inStatus = STREAM_GETDATA;
			 frameSize = ret;
			 ret =WriteOneFrameData(ch,frameSize);
			 if(ret < 0)
			 {
				 continue;
			 }
		 }
		 else
		 {
			 //没有取到数据流
			 if(pRecDataProc->Recording())
			 {
				 continue;
			 }
			 else
			 {
				 pRecCtrl->inStatus = STREAM_DATALOST;
			 }
		 }
		 curWater = FIFO_GET_FRAME_WATER(ch,0);
	}while(curWater >= LOW_WATER);

	return 0;
}

int CRecordSet::GetOneFrameData(int ch, uchar_t * frameBuf, int size)
{

	int ret  = 0;

	m_curFrm.buf = frameBuf;

	ret = MML_Read_Frame(m_curFrm.buf,size,ch,0);

	return ret;

}

int CRecordSet::WriteOneFrameData(int ch, int size)
{
	int ret	    = 0;
	bool bClose = false;
	int type    = m_vecRecParam[ch].recType;

	if(NULL == m_curFrm.buf)
	{
		return 0;
	}
	CROSS_ASSERT(m_curFrm.buf != NULL);
	uchar_t * frameBuf = m_curFrm.buf;
	CRecord1CHProc* pRecDataProc = m_pRecordCamera[ch].pRecDataProc;
	int64_t time = CFrmUtility::GetFrameTime(frameBuf);

	int frmType = CFrmUtility::GetFrameType(frameBuf);
	if(frmType == JpegFrame)
	{
		 return pRecDataProc->WritePicFile(frameBuf,size);
	}

	//如果不需要录像音频
	if(!m_pRecordCamera[ch].bWithAudio &&
		frmType == AFrame)
	{  //跳过音频
		return 0;
	}

	if(!pRecDataProc->Recording())
	{
		//录像文件首帧需要保证是关键帧
		if( pRecDataProc->isClose() &&
			!CFrmUtility::IsKeyFrame(frameBuf))
		{
			return ERR_NOT_KEY_FRAME_1STVEDIO;
		}

		if(0 == CFrmUtility::GetFrameTime(frameBuf))
		{
			return ERR_FRAME_TIME;
		}

	//	pRecDataProc->AnalyzeKeyFrm(frameBuf,size);
		ret = ProcStartRecord(ch, type,time);
		if(ret <= 0)
		{
			if(ret == ERR_INDEX_NORECIDX )
			{
				m_procBIT |= PROC_DISK_FULL;
			}
			m_procBIT |= PROC_DISK_CHECK;
			if(0 == g_pFileMangerArr.GetDiskNum())
			{
				TRACE("Disk is lost. CH %02d ret %d\n",ch,ret);
			}
			return ret;
		}
	}

	ret = pRecDataProc->WriteFrameData(frameBuf,size);
	if(ret < 0)
	{
		m_lock.Lock();
		switch (ret)
		{
		case ERR_NOT_KEY_FRAME_1STVEDIO:
		//	TRACE_ERR("Not key frame  type %c .\n",CFrmUtility::GetFrameType(frameBuf));
			break;

		case ERR_FOR_SAVE_KEY_FRAME:
			//为了确保每个文件的首帧为I帧，并且数据不丢帧．
			ret = pRecDataProc->StopRecord(type,true);

			ret = pRecDataProc->StartRecord(type,time);
			if(ret > 0)
			{
				ret = pRecDataProc->WriteFrameData(frameBuf,size);
			}
			break;

		case ERR_OVER_MAX_TIMESEC: //按时间段切换文件
		case ERR_DATA_OVER_FILE:
			//TRACE_ERR("CH%02d File is full. size %02d \n",ch,pRecDataProc->GetFileSize());
			ret = pRecDataProc->StopRecord(type,true);
			ret = pRecDataProc->StartRecord(type,time);
			if(ret > 0)
			{
				ret = pRecDataProc->WriteFrameData(frameBuf,size);
			}
			break;
		case ERR_SPACE_NOTENOUGH: //磁盘空间不足
			TRACE_ERR("CH%02d File is SPACE_NOTENOUGH. size %02d \n",ch,pRecDataProc->GetFileSize());
			ret = pRecDataProc->StopRecord(type,true);

			ret = pRecDataProc->StartRecord(type,time);
			if(ret > 0)
			{
				ret = pRecDataProc->WriteFrameData(frameBuf,size);
			}
			break;
		//时间回退
		case ERR_TM_JUMP_BACK: //时间回退处理
			TRACE_ERR("CH%02d ERR_TM_JUMP_BACK. file size %02d \n",ch,pRecDataProc->GetFileSize());
			ret = pRecDataProc->StopRecord(type,true);
			break;

		case ERR_RESOLUTIION_SWITCH: //分辨率切换需要产生分段
			TRACE_ERR("CH%02d File is jump. size %d.\n",ch,pRecDataProc->GetFileSize());
			if(pRecDataProc->GetFreeSize() >= STFS_REC_LEAST_SPACE)
			{
				bClose = false;
			}
			else
			{
				bClose = true;
			}

			ret = pRecDataProc->StopRecord(type,bClose);
			if(ret < 0)
			{
				TRACE_ERR("Stop Record fail.\n");
			}

			ret = pRecDataProc->StartRecord(type,time);
			if(ret > 0)
			{
				ret = pRecDataProc->WriteFrameData(frameBuf,size);
			}
			break;
		case ERR_FRAMETYPE_SWITCH:
			TRACE_ERR("CH%02d Record codeType switch. size %d.\n",ch,pRecDataProc->GetFileSize());
		case ERR_TM_JUMP_FORWARD:
			TRACE_ERR("CH%02d File is jump. size %d.\n",ch,pRecDataProc->GetFileSize());

			if(pRecDataProc->GetFreeSize() >= STFS_REC_LEAST_SPACE)
			{
				bClose = false;
			}
			else
			{
				bClose = true;
			}
			ret = pRecDataProc->StopRecord(type,bClose);
			if(ret < 0)
			{
				TRACE_ERR("Stop Record fail.\n");
			}

			ret = pRecDataProc->StartRecord(type,time);
			if(ret > 0)
			{
				ret = pRecDataProc->WriteFrameData(frameBuf,size);
			}
			break;
		case ERR_BAD_SECTOR://磁盘坏道
			TRACE_ERR("CH %d  Disk write bad sector data size %d.\n",ch,size);
			ret = pRecDataProc->StopRecord(type,true);

			ret = pRecDataProc->StartRecord(type,time);
			if(ret > 0)
			{
				ret = pRecDataProc->WriteFrameData(frameBuf,size);
			}
			break;
		case ERR_HDD_HARDWARE:
			TRACE_ERR("CH %d Disk hardware error data size %d.\n",ch,size);
			CallbackDiskError(0);
			ret = pRecDataProc->StopRecord(type,true);
			break;
		default:
			ret = pRecDataProc->StopRecord(type,true);
			ret = pRecDataProc->StartRecord(type,time);
			if(ret > 0)
			{
				ret = pRecDataProc->WriteFrameData(frameBuf,size);
			}
			break;
		}

		m_lock.UnLock();
		return ret;
	}
	m_wt_data += size;

	m_show_cnt++;

	return ret;
}

int CRecordSet::WriteGPSInfo(int ch, uchar_t * gpsInfo,int gpsInfoSize)
{
	int ret = 0;

	CRecord1CHProc* pRecDataProc = m_pRecordCamera[ch].pRecDataProc;
	ret = pRecDataProc->WriteGPSInfo(gpsInfo,gpsInfoSize);

	return ret;
}

int CRecordSet::GetCurFrmTm(int ch,int64_t & frmTm)
{
	int ret = 0;

	CRecord1CHProc* pRecDataProc = m_pRecordCamera[ch].pRecDataProc;
	frmTm = pRecDataProc->GetLastFrmTime();

	return ret;
}




int CRecordSet::ProcStartRecord(int ch ,int type,int64_t time)
{
	CRecord1CHProc* pRecDataProc = m_pRecordCamera[ch].pRecDataProc;

	int ret = pRecDataProc->StartRecord(type,time);
	if(ERR_OVER_MAXRECSEGS == ret)
	{
		ret = pRecDataProc->StartRecord(type,time);
	}

	return ret;
}

void CRecordSet::SetVideoParm(int ch,int width,int height,int frame_rate)
{
	CRecord1CHProc* pRecDataProc = m_pRecordCamera[ch].pRecDataProc;
	pRecDataProc->SetVideoParm(width,height,frame_rate);
}

void CRecordSet::SetAudioParm(int ch,int audio_channels, long rate, int bits, int format)
{
	CRecord1CHProc* pRecDataProc = m_pRecordCamera[ch].pRecDataProc;

	pRecDataProc->SetAudioParm(audio_channels,rate,bits,format);
}

bool CRecordSet::IsOpenManualRec(int ch)
{
#ifndef _WIN32
	if(g_storageCfg.chInfo[ch].enable)
	{
		return true;
	}
	else
	{
		 return false;
	}
#else
	if(CRecordSet::MANUAL_SWITCH & (1 << ch))
	{
		return true;
	}
	else
	{
		return false;
	}

#endif
	return false;
}

void CRecordSet::ProcStatus()
{
	if(m_procBIT & PROC_WT_BADSEC)
	{

	}

	if(m_procBIT & PROC_DISK_CHECK)
	{
//		CBAK_DISK_ACTIVE activeInfo;
//		diskNO = m_pIndexSet->GetStartRecDisk();
//		activeInfo.curIndex = diskNO;
//
//		ret = g_pDiskSet->CheckDiskStatus(diskNO);
//		m_procBIT &= ~PROC_DISK_CHECK;
//
//		diskNum = g_pDiskSet->GetRecordDiskNum(true);
//		if(m_procBIT & PROC_DISK_ADDDISK &&
//			diskNum != 0)
//		{
//
//			ret = m_pIndexSet->GetStartRecDisk();
//			diskNum = g_pDiskSet->GetDiskNum();
//			g_pDiskSet->CallBakDiskActive(ret,diskNum);
//
//			m_procBIT &= ~PROC_DISK_ADDDISK;
//		}
	}
	//
	if(m_procBIT & PROC_DISK_WAKEUP)
	{

	}

	if(m_procBIT & PROC_DISK_ERROR)
	{
		CallbackDiskError(0);
		m_procBIT &= ~PROC_DISK_ERROR;
	}

	if(m_procBIT & PROC_DISK_FULL)
	{
		m_procBIT &=~ PROC_DISK_FULL;
	}

	if(m_procBIT & PROC_NO_RECFILE)
	{

	}

	if(m_procBIT & PROC_DISK_1STREPORT)
	{
		CallbackDiskStatus();
		m_procBIT &= ~PROC_DISK_1STREPORT;
	}

	if(m_procBIT & PROC_COMMON_STATUS)
	{
		TRACE_ERR("PROC_COMMON_STATUS Get %d .\n ",m_procBIT);
		CallbackDiskStatus();
 		if(IsNeedDiskFullAlarm()) //问题单0006572:  取消直接回调磁盘满的录像图标，等到录像无可用空间的时候再
		{
			CallbackDiskFull(true);
 		}
		m_procBIT &= ~PROC_COMMON_STATUS;
	}
}

void CRecordSet::DealRecordStatus()
{
	int ch;
	RECORD_CTL_PARAM* pCtl  = NULL;
	RECORD_CAMERA*  pCamera = NULL;

	CCross_LockAuto tempLock(&m_lock);

	for(ch = 0 ; ch < (int)m_vecRecParam.size(); ch++)
	{
		CRecord1CHProc* pRecDataProc = m_pRecordCamera[ch].pRecDataProc;

		pCamera = &m_pRecordCamera[ch];
		pCtl = &m_vecRecParam[ch];

		if(!pCamera->bEnable)
		{
#ifndef _WIN32
			if( g_storageCfg.chInfo[ch].enable)
#else
			if(m_recStatusBIT & (1<<ch))
#endif
			{
				pCamera->bEnable = true;
			//	TRACE("CH%02d Re-open for record.\n",ch,pCtl->recType);
			}
		}

		if(pCtl->recTypeBak != pCtl->recType)
		{
#if 0
			if(STREAM_GETDATA == pCtl->inStatus)
			{
				recInfo.ch		 = ch;
				recInfo.diskLeaf = g_pFileMangerArr.GetFreeSpaceMB();
				strcpy(recInfo.file_name,pCamera->pRecDataProc->GetRecFile());
				pCtl->endType = recInfo.recType = pCtl->recType;
				TRACE("File name %s disk leaf %d MB ch %d .\n ",recInfo.file_name,recInfo.diskLeaf,ch);
				if( NULL != g_status_bak)
				{
					(*g_status_bak)(CALLBACK_ID_FS_RECORD_STATUS,(char*)&recInfo,sizeof(CBAK_REC_STATUS));
				}

                pCtl->recTypeBak = pCtl->recType;
			}
#endif
		}


		if(STREAM_DATALOST == pCtl->inStatus )
		{
#ifdef _WIN32
			if(pCtl->endType != RECORD_NONE)
			{
				TRACE("CH%02d recType %d STREAM data lost",ch,pCtl->recType);
			}
#else
			if(pCtl->endType != RECORD_NONE)
			{
//				recInfo.ch      = ch;
//				recInfo.recType = RECORD_NONE;
				pCtl->endType   = RECORD_NONE;
			//	TRACE("CH %02d STREAM_DATALOST end type %d\n",ch,recInfo.recType);
		//		RCFFsApiStorageCallback::call(CALLBACK_ID_FS_RECORD_STATUS,(char*)&recInfo,sizeof(CBAK_REC_STATUS));
			}
#endif
			pCtl->inStatus  &= ~STREAM_DATALOST;
			pCtl->recTypeBak = RECORD_NONE;
		}

#ifdef _WIN32
		if((m_show_cnt++%(50*15)) == 0)
#else
		if((m_show_cnt++%(30 *15* m_chnnNum)) == 0)
#endif
		{
			int dataWater = FIFO_GET_FRAME_WATER(ch,0);
			if(pRecDataProc->Recording())
			{
				TRACE("CH%02d file %s  SN %05u  percent %02d  water %d write speed %d \r\n",
					ch,pRecDataProc->GetDevName(),pRecDataProc->GetCurRecordSN() ,pRecDataProc->GetCurFilePercent(),
					dataWater,
					m_wt_speed);
			}

			//PrintTimeMs(pRecDataProc->GetLastFrmTime(),0,"last time");
		}
	}

}

void CRecordSet::CallbackRecStatus(bool bLost)
{
	int localType;
	int ch;

	for(ch = 0 ; ch < (int)m_vecRecParam.size(); ch++)
	{
	    if(!bLost)
        {
            if(m_pRecordCamera[ch].pRecDataProc->Recording())
            {
                localType =  m_vecRecParam[ch].recType ;//= type;
            }
            else
            {
                localType = RECORD_NONE;
            }
        }
        else
        {
            m_vecRecParam[ch].recType = localType = RECORD_NONE;
        }
// 		CBAK_REC_STATUS recInfo;
//
// 		recInfo.ch = ch;
// 		recInfo.recType  = localType;
// 		recInfo.diskLeaf = g_pFileMangerArr.GetFreeSpaceMB();
// 		strcpy(recInfo.file_name,pCamera->pRecDataProc->GetRecFile());
// 		if( NULL != g_status_bak)
// 		{
// 			(*g_status_bak)(CALLBACK_ID_FS_RECORD_STATUS,(char*)&recInfo,sizeof(CBAK_REC_STATUS));
// 		}
		CallbackRecStatus(ch,localType);
	}
}

void CRecordSet::CallbackRecStatus(int ch , int recType)
{
	CBAK_REC_STATUS recInfo;
	RECORD_CAMERA*  pCamera = &m_pRecordCamera[ch];

	recInfo.ch = ch;
	recInfo.recType  = recType;
	strcpy(recInfo.file_name,pCamera->pRecDataProc->GetRecFile());
	recInfo.diskLeaf =  g_pFileMangerArr.GetFreeSpaceMB();

	if( NULL != g_status_bak)
	{
		(*g_status_bak)(CALLBACK_ID_FS_RECORD_STATUS,(char*)&recInfo,sizeof(CBAK_REC_STATUS));
	}
}

void CRecordSet::CallbackDiskFull(bool bEnable)
{
	if(m_diskFullCnt >= 2)
	{
		return;
	}
	m_diskFullCnt++;

	CBAK_DISK_FULL fullInfo;
	if(bEnable)
	{
		fullInfo.ch         = 0;
		fullInfo.diskIndex  = 0;
	}
	else
	{
		fullInfo.ch         = -1;
		fullInfo.diskIndex  = -1;
	}

	if( NULL != g_status_bak)
	{
		(*g_status_bak)(CALLBACK_ID_FS_DISK_FULL,(char*)&fullInfo,sizeof(CBAK_DISK_FULL));
	}

}

void CRecordSet::CallbackDiskError(int diskNO)
{

	CBAK_DISK_ERROR errInfo;
	errInfo.diskIndex   = diskNO;
	if( NULL != g_status_bak)
	{
		(*g_status_bak)(CALLBACK_ID_FS_DISK_FULL,(char*)&errInfo,sizeof(CBAK_DISK_ERROR));
	}
}

void CRecordSet::CallbackDiskStatus()
{

// 	int ret = g_pFileMangerArr.GetRecordDiskNum(true);
// 	if(ret > 0)
// 	{
// 		if(!g_storageCfg.bCycleRec && m_diskFullCnt >= 3)
// 		{
// 			CallbackDiskFull();
// 		}
// 		else
// 		{
// 			g_pFileMangerArr.CallBakDiskActive(0,ret);
// 			m_diskFullCnt = 0;
// 		}
// 	}
// 	else
// 	{
// 		g_pFileMangerArr.CallBakDiskLost(0);
//
// 	}

}

int CRecordSet:: RestartRecord()
{
#ifndef _WIN32
	for(int i = 0 ; i < GetMaxCHNum() ; i++)
	{
		if(g_storageCfg.chInfo[i].enable)
		{
			StartRecord(i,RECORD_MANUAL);
		}
	}
#endif
	return 0;
};

int  CRecordSet::SetRecDataSource(int ch,int dataSourceID)
{
	if(ch  >= m_chnnNum)
	{
		return ERR_PARAM;
	}

	CRecord1CHProc* pRecDataProc = m_pRecordCamera[ch].pRecDataProc;
	pRecDataProc->SetDataSource(dataSourceID);
	TRACE_ERR("CH%02d Set dataSourceID %d .\n",ch,dataSourceID);

	return 0;
}

int CRecordSet::DataProcThread(void *pParam)
{
	int ret = 0;
	CRecordSet * pTask     = (CRecordSet*) pParam;
	int          chnnNum   = pTask->m_chnnNum;
	uchar_t   *  pframeBuf = NULL;
	int          frameSize = 0;
	RECORD_CAMERA	  *pRecordCamera = NULL;
	RECORD_CTL_PARAM  *pRecCtrl      = NULL;
	CRecord1CHProc	  *pRecDataProc  = NULL;
	int ch   = 0;
	int sleepTimeMS		  = 5;
	static int GET_COUNT  = 50;
	int getCount		  = -200;	//首次进入线程，快速取出缓冲中的数据
	int busy_bit          = 0;
	uint32_t bufSize      = g_storageCfg.getfrm_sz;
	CFile_manager_arr * pIndexSet = pTask->GetIndexSet();

	if(pTask->m_bThreadLive)
	{
		TRACE_ERR("Thread is running.\n");
		return 0;

	}

	pTask->m_bThreadLive = true;
	TRACE("Start record thread .ch num %d sleepTimeMS %d bufSize %d  \n",pTask->GetMaxCHNum(),sleepTimeMS,bufSize);

	TRACE("Thread ID %d  Start DataProcThread. Record index leaf %d .\r\nStart diskNO %d.Start Index %d \n",
	pTask->GetThreadID(),pIndexSet->GetLeafFileNum(),ret,pIndexSet->GetCurDiskNO());
	//pTask->InitParm();
	//等待一会儿
	pframeBuf = new uchar_t[bufSize];

	CrossSleep(100);
	TRACE_ERR(" Record thread GetLeafFileNum %d  .\n",pIndexSet->GetLeafFileNum());

	while(true)
	{
		//处理磁盘录像录满的情况
		if( !pTask->IsCyCleRec()			 &&	//没有开启循环录像
			pTask->m_recStatusBIT == 0	     && //所有通道均停止录像
			pIndexSet->GetLeafFileNum() == 0)  //没有了录像文件
		{
			while (true)
			{
				if(pTask->IsCyCleRec())				//开启了循环录像
				{
					break;
				}
				if(pIndexSet->GetLeafFileNum() > 0) //又扫描到录像文件
				{
					break;
				}
				if(pTask->IsNeedStop())
				{
					break;
				}
				CrossSleep(1500);
			}
		}

 		if(pTask->IsNeedStop())
		{
			pTask->StopProc();
			break;
		}


		while(getCount++ <= GET_COUNT)
		{
			if(pTask->IsNeedStop())
			{
				TRACE_ERR("Start go out of the record loop.\n");
				break;
			}

			for(ch = 0; ch < chnnNum; ch++)
			{
				//加速取空数据
				pRecordCamera = &(pTask->m_pRecordCamera[ch]);
				pRecDataProc  = pRecordCamera->pRecDataProc;
				pRecCtrl      = &pTask->m_vecRecParam[ch];

				if(!pRecordCamera->bEnable)
				{
					continue;
				}

				//不满足录像的条件
				if((ret = pTask->IsContentRecord(ch)) < 0)
				{
					continue;
				}

				int dataWater = FIFO_GET_FRAME_WATER(ch,0);

				if(dataWater >= 30)
				{
					busy_bit |= 1>>ch;
				}
				else
				{
					busy_bit &= ~(1>>ch);
				}

				ret =  pTask->GetOneFrameData(ch,pframeBuf,bufSize);
                if(ret <= 0)
                {
					if( 1 == chnnNum)
					{
						CrossSleep(100);
					}
					else
					{
						CrossSleep(10);
					}

                    continue;
                }

				if(ret > 0)
				{
					pRecCtrl->inStatus = STREAM_GETDATA;
					frameSize = ret;

					ret = pTask->WriteOneFrameData(ch,frameSize);

					if(ret < 0)
					{
						if(ERR_NOT_KEY_FRAME_1STVEDIO == ret)
						{
							continue;
						}
					}
					else
					{
						//没有取到数据流
						if(pRecDataProc->Recording())
						{
							continue;
						}
						else
						{
							pRecCtrl->inStatus = STREAM_DATALOST;
						}
					}
				}
			}
		}
		getCount = 0;
		if(0 == busy_bit)
		{
			//检测是否需要存储图片，主要是考虑到SD的读写效率，有规律的调试好任务
			CrossSleep(sleepTimeMS);
		}
		busy_bit = 0;
	}

	if( NULL != pframeBuf)
	{
		delete [] pframeBuf;
		pframeBuf = NULL;
	}

	pTask->m_bThreadLive = false;
	TRACE_ERR("End DataProcThread.\n");
	return 0;
}

int PUB_THREAD_CALL CRecordSet::TimerThread(void *pParam)
{
	CRecordSet		 *pTask = (CRecordSet*) pParam;
	RECORD_CAMERA	 *pRecordCamera = NULL;
	CRecord1CHProc*  pRecDataProc   = NULL;
	CSchedule		 *pSchedule     = NULL;
	RECORD_CTL_PARAM *pCtrl         = NULL;
	const int		 sleepMS         = 200;

	int chnnNum = pTask->GetMaxCHNum();
	int type    = RECORD_SCHEDULE;
	time_t nSec = 0;
	int ch      = 0;

	CrossSleep(1000);
	if(pTask->m_bTimeTheadLive)
	{
		TRACE_ERR("TimerThread is running.\n");
		return -1;
	}

	pTask->m_bTimeTheadLive = true;;

	pTask->CallbackDiskStatus();

	while(true)
	{
		if(pTask->IsNeedStop())
		{
			for(ch = 0; ch < chnnNum; ch++)
			{
			    if(!pTask->IsOpenManualRecord(ch))
				{
				    pTask->StopRecord(ch,type);
                }
			}

			pTask->m_bTimeTheadLive = false;
			pTask->DealRecordStatus();
			TRACE_ERR("End time thread.\n");
			break;
		}

		pTask->DealAlarmRec();
		pTask->DealRecordStatus();

		time(&nSec);

		//检测磁盘写入速度
		pTask->CountWtSpeed(nSec);

		//检查磁盘是否已经满了，
		pTask->CheckDiskFull(nSec);

#if 0
		 //手动与计划录像控制
		for(ch = 0; ch < chnnNum; ch++)
		{
			pRecordCamera = &(pTask->m_pRecordCamera[ch]);
			pRecDataProc  = pRecordCamera->pRecDataProc;
			pSchedule     = pTask->m_vecRecParam[ch].pSchedule;
			pCtrl         = &(pTask->m_vecRecParam[ch]);

			if(pTask->IsOpenManualRecord(ch))
			{   //自动开启手动录像
				if(!pRecDataProc->Recording())
				{
					pTask->StartRecord(ch,RECORD_MANUAL);
				}
			}
			else
			{
				if(!pSchedule->IsEnable())
				{
					if((pRecDataProc->RealRecordType() == RECORD_SCHEDULE) &&
						pRecDataProc->Recording())
					{
						pTask->StopRecord(ch,type);
					}
					continue;
				}

				if(pSchedule->IsEffectTime(nSec))
				{
					if( STREAM_DATALOST != pCtrl->inStatus)
					{
						if(type > pTask->m_vecRecParam[ch].recType &&
							g_pFileMangerArr.GetDiskNum() != 0	)
						{
							pTask->StartRecord(ch,type);
						}
					}
				}
				else
				{
					if( type == pTask->m_vecRecParam[ch].recType)
					{
						pTask->StopRecord(ch,type);
					}
				}
			}
		}
#endif
		CrossSleep(sleepMS);
	}
	pTask->m_bTimeTheadLive = false;
	return 0;
}

//默认5S秒种计算一次
int CRecordSet::CountWtSpeed(time_t now, int countSecs)
{
	uint32_t dataSize = 0;
	if( 0 == now)
	{
		time(&now);
	}
	if(ABS(now - m_lastCoutTime) > countSecs)
	{
		if(m_wt_data >= m_wt_bak)
		{
			dataSize = (m_wt_data - m_wt_bak);
		}
		else
		{
			dataSize = m_wt_data + (SIZE_GB(4) - m_wt_bak);
		}

		m_wt_bak   = m_wt_data;
		m_wt_speed =(dataSize / countSecs)/1024 ;
		m_lastCoutTime = now;
	}

	return 0;
}

bool  CRecordSet::CheckDiskFull(time_t now,int countSecs)
{
	if( 0 == now)
	{
		time(&now);
	}

	//间隔3S检查一下。
	if(ABS(now - m_lastCeckDiskFullTm) > countSecs)
	{
		m_lastCeckDiskFullTm = now;
		//没有一个初始化过的磁盘，就一定不会是磁盘满
		if(0 == m_pIndexSet->GetDiskNum())
		{
			return false;
		}

		if( !IsCyCleRec()					   &&  //没有开启循环覆盖
			0 == m_pIndexSet->GetLeafFileNum() &&  //剩余预录像文件个数为0
			IsHaveChannelStopRec())               //有任意一个通道已经停止录像
		{
			CRecordSet::m_procBIT |= CRecordSet::PROC_DISK_FULL;
			TRACE("Detect disk is full.\n");
			PrintTimeSec(now,0,"Detected time");
			CallbackDiskFull();
			return true;
		}
	}
	return false;
}

